package study.alex.resumedb.gae;

import com.google.appengine.api.users.UserServiceFactory;
import com.vaadin.addon.jpacontainer.EntityItem;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.util.BeanItem;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.*;
import study.alex.resumedb.gae.model.Contact;
import study.alex.resumedb.gae.model.Resume;
import study.alex.resumedb.gae.model.resumeTracker;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.GregorianCalendar;
import java.util.logging.Logger;

/**
 * Created with IntelliJ IDEA.
 * User: alex
 * Date: 27.01.14
 * Time: 12:29
 * SVN $Id$
 */
public class HistoryAddWindow extends Window implements Button.ClickListener {

    private final Button saveButton;
    private final Button cancelButton;
    private final FieldGroup editorForm;
    private final Item historyItem;
    private final Resume resume;
    private final Table contacts = new ContactTable(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("select.employer.contact"), UserServiceFactory.getUserService().getCurrentUser().getUserId());
    private final Label resumeInfo = new Label("", ContentMode.PREFORMATTED);
    private final FormLayout historyForm = new FormLayout();
    private final JPAContainerForTracker container;

    public HistoryAddWindow(Item resumeItem, JPAContainerForTracker container) {
        assert resumeItem != null : "Resume have to present";
        assert container != null : "Container have to present";

        this.resume = ((EntityItem<Resume>)resumeItem).getEntity();
        this.container = container;
        GregorianCalendar today = new GregorianCalendar();
        Object ref = contacts.getValue();
        Contact curContact = null;
        if (ref != null) {
            curContact = ((EntityItem<Contact>)contacts.getItem(ref)).getEntity();
        }

        resumeTracker newTracker = new resumeTracker(resume.getUserId(), curContact, today, this.resume);
        historyItem = new BeanItem<resumeTracker>(newTracker);

        editorForm = new BeanFieldGroup<resumeTracker>(resumeTracker.class);
        editorForm.setItemDataSource(historyItem);
        editorForm.setBuffered(true);
        editorForm.addCommitHandler(new FieldGroup.CommitHandler() {
            @Override
            public void preCommit(FieldGroup.CommitEvent commitEvent) throws FieldGroup.CommitException {
                if (!commitEvent.getFieldBinder().isValid() || contacts.getValue() == null) {
                    throw new FieldGroup.CommitException("Input data is not valid or contact wasn't selecting");
                }
            }

            @Override
            public void postCommit(FieldGroup.CommitEvent commitEvent) throws FieldGroup.CommitException {
            }
        });

        saveButton = new Button(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("save"), this);
        cancelButton = new Button(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("cancel"), this);

        HorizontalLayout buttons = new HorizontalLayout(saveButton, cancelButton);
        buttons.setSizeUndefined();
        buttons.setSpacing(true);

        String emplId = (String)historyItem.getItemProperty("employer").getValue();
        Contact empl = getEmployer(emplId);

        if (empl != null) fillSentResumeContactInfo(empl.getName(), empl.getOrganization(), empl.getPhones(), empl.getEmails());

        final DateField sentField = new DateField(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("sent.date"));
        sentField.setConverter(new DateConverter());
        editorForm.bind(sentField, "sentdate");
        final DateField checkField = new DateField(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("check.call"));
        checkField.setConverter(new DateConverter());
        editorForm.bind(checkField, "checkcall");

        historyForm.addComponents(sentField, checkField, editorForm.buildAndBind(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("comment"), "comment", TextArea.class));

        VerticalLayout rightPanel = new VerticalLayout(resumeInfo, historyForm, buttons);
        rightPanel.setComponentAlignment(resumeInfo, Alignment.TOP_CENTER);
        rightPanel.setComponentAlignment(historyForm, Alignment.TOP_CENTER);
        rightPanel.setComponentAlignment(buttons,Alignment.BOTTOM_RIGHT);
        rightPanel.setSpacing(true);
        rightPanel.setSizeFull();

        contacts.setSizeFull();
        contacts.setMultiSelect(false); //TODO make multiselect history mode
        contacts.addValueChangeListener(new Property.ValueChangeListener() {
            @Override
            public void valueChange(Property.ValueChangeEvent event) {
                Object ref = contacts.getValue();
                if (ref != null) {
                    String curContactId = ((EntityItem<Contact>)contacts.getItem(ref)).getEntity().getId();
                    Logger.getLogger(HistoryAddWindow.class.getName()).fine("Change select in contact table.  New select id " + curContactId);
                    historyItem.getItemProperty("employer").setValue(curContactId);
                    Contact empl = getEmployer((String)ref);
                    if (empl != null) fillSentResumeContactInfo(empl.getName(), empl.getOrganization(), empl.getPhones(), empl.getEmails());
                }
            }
        });

        //root panel
        final HorizontalLayout rootPanel = new HorizontalLayout(contacts, rightPanel);
        rootPanel.setSpacing(true);
        rootPanel.setMargin(true);
        rootPanel.setComponentAlignment(contacts, Alignment.TOP_CENTER);
        rootPanel.setComponentAlignment(rightPanel, Alignment.TOP_CENTER);
        rootPanel.setSizeFull();
        setWidth("60%");
        setHeight("50%");
        setContent(rootPanel);
        setCaption(buildCaption());
        center();
        setModal(true);
    }

    private Contact getEmployer(String id) {
        if (id == null || id.isEmpty()) return null;

        EntityManager em = JPAContainerFactory.createEntityManagerForPersistenceUnit(EMF.PERSISTENCE_UNIT);

        try {
            Contact ct = em.find(Contact.class, id);
            Logger.getLogger(HistoryUpdateStatusWindow.class.getName()).fine("Got Contact info: " + ct);
            return ct;
        } finally {
            em.close();
        }
    }

    private void fillSentResumeContactInfo(String name, String pos, String phones, String emails) {
        if (name != null && pos != null && phones != null && emails != null) {
            resumeInfo.setValue(
                    (name.equals("") ? "" : (MessageFormat.format(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("person.0"), name))) +
                            (pos.equals("") ? "" : (MessageFormat.format(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("organization.0"), pos))) +
                            (phones.equals("") ? "" : (MessageFormat.format(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("phones.0"), phones))+" ") +
                            (emails.equals("") ? "" : (MessageFormat.format(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("e.mails.0"), emails))));
        }
        else resumeInfo.setValue("");
    }

    /**
     * @return the caption of the editor window
     */
    private String buildCaption() {
        return String.format(((ResumeDBMaintUI) UI.getCurrent()).getBundle().getString("add.sent.record.position.s"), resume.getPosition());
    }

    @Override
    public void buttonClick(Button.ClickEvent event) {
        if (event.getButton() == saveButton) {
                        try {
                            editorForm.commit();
                            Object ref = container.addEntity(((BeanItem<resumeTracker>)historyItem).getBean());
                            if (ref != null) {
                                fireEvent(new EditorSavedEvent(this, container.getItem(ref)));
                            } else {
                                Logger.getLogger(HistoryAddWindow.class.getName()).fine("Error was when add history record");
                                return;
                            }
                        } catch (FieldGroup.CommitException e) {
                            Logger.getLogger(HistoryAddWindow.class.getName()).fine("Error in input data in Add History Form");
                            return;
                        }
        } else if (event.getButton() == cancelButton) {
                    editorForm.discard();
        }
        close();
    }

    public void addListener(EditorSavedListener listener) {
        try {
            Method method = EditorSavedListener.class.getDeclaredMethod(
                    "editorSaved", new Class[] { EditorSavedEvent.class });
            addListener(EditorSavedEvent.class, listener, method);
        } catch (final java.lang.NoSuchMethodException e) {
            // This should never happen
            throw new java.lang.RuntimeException(
                    "Internal error, editor saved method not found");
        }
    }

    public void removeListener(EditorSavedListener listener) {
        removeListener(EditorSavedEvent.class, listener);
    }

    public static class EditorSavedEvent extends Component.Event {

        private Item savedItem;

        public EditorSavedEvent(Component source, Item savedItem) {
            super(source);
            this.savedItem = savedItem;
        }

        public Item getSavedItem() {
            return savedItem;
        }
    }

    public interface EditorSavedListener extends Serializable {
        public void editorSaved(EditorSavedEvent event);
    }
}
